#include "bsp_gpt.h"

/**
 * @brief 				GPT初始化
 *
 * @param GPT 		GPT1 | GPT2 | GPT3
 * @param frac		分频值 0x000 - 0xFFF
 * @param value		比较值
 * @param OCR		  输出通道 0 | 1 | 2
 */
void GPT_Init(GPT_Type *GPT, unsigned int frac, unsigned int value,
              unsigned int OCR) {
  if (frac >= 0xfff) {
    frac = 0xfff;
  }

  GPT->CR = 0;
  GPT->CR |= (0x1 << 15);
  while ((GPT->CR >> 15) & 0x1)
    ;
  /*
   * GPT 的 CR 寄存器,GPT 通用设置 GPT控制寄存器
   *
   *  bit22:20 	000 输出比较 1 的输出功能关闭，也就是对应的引脚没反应
   *  bit15
   *  bit9:0   	Restart 模式(只有输出比较寄存器1才有这个模式),
   *						当 CNT 等于 OCR1
   *						的时候就产生中断
   *
   *  bit8:6   	001 GPT 时钟源选择 ipg_clk=66Mhz
   *  bit1     	1 当计数器被禁用时，计数器值重置为0
   *  bit0     	1 使能GPT
   */
  GPT->CR |= (0x1 << 6);
  GPT->CR |= (0x1 << 1);

  /*
   * GPT 的 PR 寄存器， GPT 的分频设置
   *
   *  bit11:0 	设置分频值，设置为 0 表示 1 分频，
   *  					以此类推，最大可以设置为
   * 0XFFF，也就是最大 4096 分频 66 分频， GPT1 时钟为 66M/(65+1)=1MHz
   */
  GPT->PR &= ~(0xFFF);
  GPT->PR |= (frac);

  /*
   * GPT 的 OCR1 寄存器， GPT 的输出比较 1 比较计数值，
   * 当 GPT 的计数值等于 OCR1 里面值时候，输出比较 1 就会发生中断
   * 这里定时 500ms 产生中断，因此就应该为 1000000/2=500000;
   */
  GPT->OCR[OCR] = value;

  /*
   * GPT 的 OCR1 寄存器， GPT 的输出比较 1 比较计数值，
   * GPT 的时钟为 1Mz，那么计数器每计一个值就是就是 1us。
   * 为了实现较大的计数，我们将比较值设置为最大的 0XFFFFFFFF,
   * 这样一次计满就是： 0XFFFFFFFFus = 4294967296us = 4295s = 71.5min
   * 也就是说一次计满最多 71.5 分钟，存在溢出。
   */
}

/**
 * @brief       使能GIC对应中断
 *
 * @param IRQ   中断号
 */
void GPT_GIC_EnableIRQ(IRQn_Type IRQ) { GIC_EnableIRQ(IRQ); }

/**
 * @brief             注册中断服务函数
 *
 * @param irq         中断号
 * @param handler     中断服务函数
 * @param userParam   中断服务处理函数参数
 */
void GPT_IRQ_Handler(IRQn_Type irq, system_irq_handler_t handler,
                     void *userParam) {
  system_register_irqhandler(irq, handler, userParam);
}

/**
 * @brief       使能GPT
 *
 * @param GPT   GPT1 | GPT2 | GPT3
 */
void GPT_Enabled(GPT_Type *GPT) { GPT->CR |= (0x1); }

/**
 * @brief       禁用GPT
 *
 * @param GPT   GPT1 | GPT2 | GPT3
 */
void GPT_Disabled(GPT_Type *GPT) { GPT->CR &= ~(0x1); }

/**
 * @brief       开启GPT中断
 * @brief       bit5:3  输入比较中断使能(1)
 * @brief       bit2:0  输出比较中断使能(1)
 *
 * @param GPT    GPT1 | GPT2 | GPT3
 * @param bit    0---5
 */
void GPT_IR(GPT_Type *GPT, unsigned int bit) {
  /*
   *  GPT 的 IR 寄存器 中断寄存器
   *
   *  bit5:3  输入比较中断使能(1)
   *  bit2:0  输出比较中断使能(1)
   */

  GPT->IR |= (0x1 << bit);
}